// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: auto_link.hpp 287 2008-11-27 14:32:14Z heavyzheng $
//

//
// Automatic library inclusion for Borland/Microsoft compilers.
//


////////////////////////////////////////////////////////////////////////////////////////////////////

/**

Usage:
~~~~~~

Before including this header you must define one or more of the following macros:

ZZHENG_AUTO_LINK_LIB_NAME : Required. The basename of the library (for example: zzheng_xml).
ZZHENG_AUTO_LINK_SUFFIX   : Optional. The library name suffix.
ZZHENG_AUTO_LINK_TOOLSET  : Optional. The name and version of the toolset.
ZZHENG_AUTO_LINK_SHARED   : Optional. When defined, link to shared library rather than static one.
ZZHENG_AUTO_LINK_DIAG     : Optional. When set, print out the name of the library selected.

These macros will be undef'ed at the end of the header, further this header has no include guards,
so be sure to include it only once from your library!

Algorithm:
~~~~~~~~~~

Libraries for Borland and Microsoft compilers are automatically selected here, the name of the
library is selected according to the following formula:

ZZHENG_AUTO_LINK_LIB_PREFIX
    + ZZHENG_AUTO_LINK_LIB_NAME
    + "_"
    + ZZHENG_AUTO_LINK_TOOLSET
    + ZZHENG_AUTO_LINK_THREADING
    + ZZHENG_AUTO_LINK_RUNTIME
    + "-"
    + ZZHENG_AUTO_LINK_VERSION
    + ZZHENG_AUTO_LINK_SUFFIX
    + ".lib"

These are defined as:

ZZHENG_AUTO_LINK_LIB_PREFIX : "lib" for static libraries otherwise "".
ZZHENG_AUTO_LINK_LIB_NAME   : The base name of the library (for example: "zzheng_xml").
ZZHENG_AUTO_LINK_TOOLSET    : The compiler toolset name (vc70, vc80, etc).
ZZHENG_AUTO_LINK_THREADING  : "-mt" for multi-thread builds, otherwise nothing.
ZZHENG_AUTO_LINK_RUNTIME    : A suffix that indicates the runtime library used, contains one or
                              more of the following letters after a hyphen:
                              s - static runtime (dynamic if not present).
                              d - debug build (release if not present).
                              g - debug/diagnostic runtime (release if not present).
ZZHENG_AUTO_LINK_VERSION    : The library version, in the form x_y_z, for version x.y.z.
ZZHENG_AUTO_LINK_SUFFIX     : The library name suffix, typically starting with a hyphen.

*/

#include <zzheng/version.hpp>

//
// Only include what follows for known and supported compilers:
//
#if defined(ZZHENG_MSVC) \
    || defined(__BORLANDC__) \
    || ( defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000) ) \
    || ( defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200) )


#ifndef ZZHENG_AUTO_LINK_VERSION
#  define ZZHENG_AUTO_LINK_VERSION ZZHENG_VERSION_STR
#endif // ZZHENG_AUTO_LINK_VERSION

#ifndef ZZHENG_AUTO_LINK_LIB_NAME
#  error "[zzheng] macro ZZHENG_AUTO_LINK_LIB_NAME not defined (internal error)"
#endif // !ZZHENG_AUTO_LINK_LIB_NAME

#ifndef ZZHENG_AUTO_LINK_SUFFIX
#  define ZZHENG_AUTO_LINK_SUFFIX_SEP
#  define ZZHENG_AUTO_LINK_SUFFIX
#else
#  define ZZHENG_AUTO_LINK_SUFFIX_SEP "-"
#endif // ZZHENG_AUTO_LINK_SUFFIX


//
// error check:
// TODO:
//
#if defined(__MSVC_RUNTIME_CHECKS) && !defined(_DEBUG)
#  pragma message("[zzheng] setting /RTC (runtime checks) without specifying a debug runtime will lead to linker errors")
#  pragma message("[zzheng] hint: go to the code generation options and switch to one of the debugging runtimes")
#  error "[zzheng] incompatible build options"
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// Select toolset if not #define'd already
//

#ifndef ZZHENG_AUTO_LINK_TOOLSET
// Note: compilers before 1200 are not supported.
#  if defined(ZZHENG_MSVC) && (ZZHENG_MSVC < 1300) // evc4 or vc60
#    ifdef UNDER_CE
#      define ZZHENG_AUTO_LINK_TOOLSET "evc4"
#    else
#      define ZZHENG_AUTO_LINK_TOOLSET "vc60"
#    endif // UNDER_CE
#  elif defined(ZZHENG_MSVC) && (ZZHENG_MSVC == 1300) // vc70
#    define ZZHENG_AUTO_LINK_TOOLSET "vc70"
#  elif defined(ZZHENG_MSVC) && (ZZHENG_MSVC == 1310) // vc71
#    define ZZHENG_AUTO_LINK_TOOLSET "vc71"
#  elif defined(ZZHENG_MSVC) && (ZZHENG_MSVC >= 1400) // vc80
#    define ZZHENG_AUTO_LINK_TOOLSET "vc80"
#  elif defined(__BORLANDC__) // Borland C++ Builder 6
#    define ZZHENG_AUTO_LINK_TOOLSET "bcb"
#  elif defined(__ICL) // Intel C++, no version number
#    define ZZHENG_AUTO_LINK_TOOLSET "iw"
#  elif defined(__MWERKS__) && (__MWERKS__ <= 0x31FF ) // Metrowerks CodeWarrior 8.x
#    define ZZHENG_AUTO_LINK_TOOLSET "cw8"
#  elif defined(__MWERKS__) && (__MWERKS__ <= 0x32FF ) // Metrowerks CodeWarrior 9.x
#    define ZZHENG_AUTO_LINK_TOOLSET "cw9"
#  endif
#endif // !ZZHENG_AUTO_LINK_TOOLSET


////////////////////////////////////////////////////////////////////////////////////////////////////
// Select threading
//

#if defined(_MT) || defined(__MT__)
#  define ZZHENG_AUTO_LINK_THREADING "-mt"
#else
#  define ZZHENG_AUTO_LINK_THREADING
#endif


////////////////////////////////////////////////////////////////////////////////////////////////////
// Select runtime
//

#if defined(_MSC_VER) || defined(__MWERKS__)

#  ifdef _DLL
#    ifdef _DEBUG
#      define ZZHENG_AUTO_LINK_RUNTIME "-gd"
#    else
#      define ZZHENG_AUTO_LINK_RUNTIME
#    endif
#  else
#    ifdef _DEBUG
#      define ZZHENG_AUTO_LINK_RUNTIME "-sgd"
#    else
#      define ZZHENG_AUTO_LINK_RUNTIME "-s"
#    endif
#  endif // _DLL

#elif defined(__BORLANDC__)

// Figure out whether we want the debug builds or not:
#  if __BORLANDC__ > 0x561
#    pragma defineonoption BOOST_BORLAND_DEBUG -v
#  endif

// Sanity check:
#  if defined(__STL_DEBUG) || defined(_STLP_DEBUG)
#    error "[zzheng] pre-built versions of the zzheng libraries are not provided in STLPort-debug form"
#  endif

#  ifdef _RTLDLL
#    ifdef ZZHENG_BORLAND_DEBUG // TODO: what is this macro?
#      define ZZHENG_AUTO_LINK_RUNTIME "-d"
#    else
#      define ZZHENG_AUTO_LINK_RUNTIME
#    endif
#  else
#    ifdef ZZHENG_BORLAND_DEBUG
#      define ZZHENG_AUTO_LINK_RUNTIME "-sd"
#    else
#      define ZZHENG_AUTO_LINK_RUNTIME "-s"
#    endif
#  endif

#endif


////////////////////////////////////////////////////////////////////////////////////////////////////
// Select linkage option
//
#if ( defined(_DLL) || defined(_RTLDLL) ) && defined(ZZHENG_AUTO_LINK_SHARED)
#  define ZZHENG_AUTO_LINK_LIB_PREFIX
#elif defined(ZZHENG_AUTO_LINK_SHARED)
#  error "[zzheng] mixing a shared zzheng library with a static runtime is a really bad idea..."
#else
#  define ZZHENG_AUTO_LINK_LIB_PREFIX "lib"
#endif


////////////////////////////////////////////////////////////////////////////////////////////////////
// Now include the library
//

#if defined(ZZHENG_AUTO_LINK_LIB_PREFIX)   \
    && defined(ZZHENG_AUTO_LINK_LIB_NAME)  \
    && defined(ZZHENG_AUTO_LINK_TOOLSET)   \
    && defined(ZZHENG_AUTO_LINK_THREADING) \
    && defined(ZZHENG_AUTO_LINK_RUNTIME)   \
    && defined(ZZHENG_AUTO_LINK_VERSION)

#  define ZZHENG_AUTO_LINK_FULL_NAME  ZZHENG_AUTO_LINK_LIB_PREFIX \
                                      ZZHENG_AUTO_LINK_LIB_NAME   \
                                      "-"                         \
                                      ZZHENG_AUTO_LINK_TOOLSET    \
                                      ZZHENG_AUTO_LINK_THREADING  \
                                      ZZHENG_AUTO_LINK_RUNTIME    \
                                      "-"                         \
                                      ZZHENG_AUTO_LINK_VERSION    \
                                      ZZHENG_AUTO_LINK_SUFFIX_SEP \
                                      ZZHENG_AUTO_LINK_SUFFIX     \
                                      ".lib"
#  pragma comment(lib, ZZHENG_AUTO_LINK_FULL_NAME)
#  ifdef ZZHENG_AUTO_LINK_DIAG
#    pragma message("[zzheng] auto-linking to: " ZZHENG_AUTO_LINK_FULL_NAME)
#  endif // ZZHENG_AUTO_LINK_DIAG

#else
#  error "[zzheng] some required macros where not defined (internal error)."
#endif


#endif // supported compilers


////////////////////////////////////////////////////////////////////////////////////////////////////
// #undef any macros we may have set
//

#ifdef ZZHENG_AUTO_LINK_FULL_NAME
#  undef ZZHENG_AUTO_LINK_FULL_NAME
#endif // ZZHENG_AUTO_LINK_FULL_NAME

#ifdef ZZHENG_STRINGIZE
#  undef ZZHENG_STRINGIZE
#endif // ZZHENG_STRINGIZE

#ifdef ZZHENG_AUTO_LINK_LIB_PREFIX
#  undef ZZHENG_AUTO_LINK_LIB_PREFIX
#endif // ZZHENG_AUTO_LINK_LIB_PREFIX

#ifdef ZZHENG_AUTO_LINK_LIB_NAME
#  undef ZZHENG_AUTO_LINK_LIB_NAME
#endif // ZZHENG_AUTO_LINK_LIB_NAME

#ifdef ZZHENG_AUTO_LINK_SUFFIX_SEP
#  undef ZZHENG_AUTO_LINK_SUFFIX_SEP
#endif // ZZHENG_AUTO_LINK_SUFFIX_SEP

#ifdef ZZHENG_AUTO_LINK_SUFFIX
#  undef ZZHENG_AUTO_LINK_SUFFIX
#endif // ZZHENG_AUTO_LINK_SUFFIX

#ifdef ZZHENG_AUTO_LINK_LIB_NAME
#  undef ZZHENG_AUTO_LINK_LIB_NAME
#endif // ZZHENG_AUTO_LINK_LIB_NAME

#ifdef ZZHENG_AUTO_LINK_VERSION
#  undef ZZHENG_AUTO_LINK_VERSION
#endif // ZZHENG_AUTO_LINK_VERSION

#ifdef ZZHENG_AUTO_LINK_THREADING
#  undef ZZHENG_AUTO_LINK_THREADING
#endif // ZZHENG_AUTO_LINK_THREADING

#ifdef ZZHENG_AUTO_LINK_RUNTIME
#  undef ZZHENG_AUTO_LINK_RUNTIME
#endif // ZZHENG_AUTO_LINK_RUNTIME

#ifdef ZZHENG_AUTO_LINK_SHARED
#  undef ZZHENG_AUTO_LINK_SHARED
#endif // ZZHENG_AUTO_LINK_SHARED

//
// Don't #undef the following macros:
// they can be set by the user and should be the same for all libraries.
//

// #ifdef ZZHENG_AUTO_LINK_TOOLSET
// #  undef ZZHENG_AUTO_LINK_TOOLSET
// #endif // ZZHENG_AUTO_LINK_TOOLSET






